/** =====================================================
 * Copyright © hk. 2022-2025. All rights reserved.
 * File name  : 02_sem_task_pool.c
 * Author     : 上上签
 * Date       : 2023-12-05
 * Version    : 
 * Description: 
 * ======================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <aos/kernel.h>
#include "aos/init.h"
#include "board.h"
#include <k_api.h>
#include "aos/hal/gpio.h"
#include "ulog/ulog.h"

#define RED_LED   0 // PA14
#define GRE_LED   1 // PA15

#define KEY1_PORT 8 // PA5
#define KEY2_PORT 2 // PA22
#define KEY3_PORT 4 // PA23

#define TASK_KEY_NAME       "task_key"
#define TASK_POOL_NAME 		"task_pool"
#define APP_MOUDLE_NAME 	"task_pool"
#define TASK_EXEC_NUMBER    5


gpio_dev_t  led_gpio_dev[2] = {0}; 
gpio_dev_t  key_gpio_dev;
uint32_t    key_value;

aos_sem_t   key_sem;
aos_sem_t   pool_sem;
aos_sem_t   exec_sem;

const char * task_exec_names[TASK_EXEC_NUMBER] = 
{
    "task_exec1",
    "task_exec2",
    "task_exec3",
    "task_exec4",
    "task_exec5",
};

//任务池 执行任务
void task_exec_entry(void *arg)
{
    int ret;
    const char * task_name;
    task_name = aos_task_name();
    while(1)
    {
        //等待任务执行命令
		ret = aos_sem_wait(&exec_sem, AOS_WAIT_FOREVER);
		if(ret != 0)
		{
			LOGE(APP_MOUDLE_NAME,"task key sem wait err\r\n");
		}
        else
        {
            //打印任务执行信息
            LOGI(APP_MOUDLE_NAME, "%s is run\r\n", task_name);
            aos_msleep(10000);
            LOGI(APP_MOUDLE_NAME, "%s is stop\r\n", task_name);
            //释放任务池资源
            aos_sem_signal(&pool_sem);
        }
    }
}

// 任务池 任务管理
void task_pool_entry(void *pool)
{
	int ret;

	while(1)
    {
        //等待按键按下
		ret = aos_sem_wait(&key_sem, AOS_WAIT_FOREVER);
		if(ret != 0)
		{
			LOGE(APP_MOUDLE_NAME,"task key sem wait err\r\n");
		}
		else
		{
            //获取线程池
            ret = aos_sem_wait(&pool_sem, AOS_WAIT_FOREVER);
		    if(ret != 0)
		    {
			    LOGE(APP_MOUDLE_NAME,"task pool sem wait err\r\n");
		    }
            else
            {
                //若有空闲的任务可用，那么让任务执行
                aos_sem_signal(&exec_sem);
            }
		}
	}
}

// 按键检测任务
void task_key_entry(void *arg)
{
    while(1) 
    {
        hal_gpio_input_get(&key_gpio_dev, &key_value);
        if(!key_value)
        {
            //延时去抖动
           aos_msleep(10);
           //再次判断是否按下
           hal_gpio_input_get(&key_gpio_dev, &key_value);
           if(!key_value)
           {
                printf("key is down!send key_sem!\r\n");
				aos_sem_signal(&key_sem);
                //等待按键松开
                do{
                    hal_gpio_input_get(&key_gpio_dev, &key_value);
                    aos_msleep(10);
                }while(!key_value);
           }

        }
        //10ms 读取一次按键状态
        aos_msleep(10);
    }
}

int led_init(void)
{
    //由于PA14时rtl8710的jtag接口，我要使用GPIO功能，必须先关闭jtag借口
    sys_jtag_off();
    led_gpio_dev[0].port = RED_LED;
    led_gpio_dev[0].config = OUTPUT_PUSH_PULL;
    led_gpio_dev[0].priv = NULL;
    //gpio PA14初始化
    hal_gpio_init(&led_gpio_dev[0]);

    led_gpio_dev[1].port = GRE_LED;
    led_gpio_dev[1].config = OUTPUT_PUSH_PULL;
    led_gpio_dev[1].priv = NULL;
    //gpio PA14初始化
    hal_gpio_init(&led_gpio_dev[1]);

    return 0;
}

int application_start(int argc, char *argv[])
{
    int ret = 0;
    int index = 0;

    led_init();
    key_gpio_dev.port = KEY1_PORT;
    //根据原理图分析配置位输入上拉模式
    key_gpio_dev.config = INPUT_PULL_UP;
    key_gpio_dev.priv = NULL;
    //key 初始化
    hal_gpio_init(&key_gpio_dev);

    aos_set_log_level(AOS_LL_INFO);

     //创建按键同步信号量
	ret = aos_sem_new(&key_sem, 0);
	if(ret != 0)
	{
		LOGE(APP_MOUDLE_NAME,"task key sem create err\r\n");
	}
    //创建任务池资源共享信号量
	ret = aos_sem_new(&pool_sem, 5);
	if(ret != 0)
	{
		LOGE(APP_MOUDLE_NAME,"task pool sem create err\r\n");
	}
    //创建任务池同步信号量
    ret = aos_sem_new(&exec_sem, 0);
    if(ret != 0)
    {
        LOGE(APP_MOUDLE_NAME,"task pool sem create err\r\n");
	}

    //创建5个任务数量的任务池
    for(index = 0; index < TASK_EXEC_NUMBER; index++)
    {
        ret = aos_task_new(task_exec_names[index], task_exec_entry, NULL, 8*128);
        if(ret != 0)
        {
            LOGE(APP_MOUDLE_NAME,"%s create err\r\n", task_exec_names[index]);
        }

    }
    //创建按键检测任务
	ret = aos_task_new(TASK_KEY_NAME, task_key_entry, NULL, 8*128);
	if(ret != 0)
	{
		LOGE(APP_MOUDLE_NAME,"task key create err\r\n");
	}
    //创建任务池分配任务
	ret = aos_task_new(TASK_POOL_NAME, task_pool_entry, NULL, 8*128);
	if(ret != 0)
	{
		LOGE(APP_MOUDLE_NAME,"task led create err\r\n");
	}

    while(1)
    {
        aos_msleep(1000);
        hal_gpio_output_toggle(&led_gpio_dev[1]);
    }
  
}
